package com.lap.auth.filter;

import com.lap.auth.application.authorization.AuthorQueryService;
import com.lap.auth.application.authorization.dto.ApiDto;
import com.lap.auth.application.authorization.dto.PermissionDto;
import com.lap.auth.shared.errors.UserError;
import com.lap.context.starter.core.helper.MessageHelper;
import com.lap.framework.common.constant.Header;
import com.lap.framework.common.dto.result.Result;
import com.lap.framework.common.exception.BizException;
import com.lap.framework.common.tool.JsonUtil;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.filter.OncePerRequestFilter;

/**
 * 授权拦截器
 *
 * @author Shuisheng Lao(劳水生)
 * @version 0.0.1
 */
@Slf4j
@RequiredArgsConstructor
public class AuthorizationFilter extends OncePerRequestFilter {
  private static final String NOT_AUTHOR = "%s: %s is not author";

  private final Security security = new Security();
  private final AuthorQueryService authorQueryService;
  private final MessageHelper messageHelder;

  @Override
  protected void doFilterInternal(
      HttpServletRequest request,
      @NonNull HttpServletResponse response,
      @NonNull FilterChain filterChain)
      throws ServletException, IOException {
    String uri = request.getRequestURI();
    String method = request.getMethod();
    boolean ignoreAuthor = security.ignoreAuthor(request.getRequestURI(), request.getMethod());
    if (ignoreAuthor) {
      filterChain.doFilter(request, response);
      return;
    }

    try {
      Integer userId = Integer.valueOf(request.getHeader(Header.USER_ID));
      PermissionDto dto = authorQueryService.getPermission(userId);
      PermissionMatcher matcher = new PermissionMatcher();
      ApiDto api = matcher.match(dto.getApiList(), uri, method).orElse(null);
      if (api != null) {
        filterChain.doFilter(request, response);
        return;
      }

      log.warn("未授权:{}", String.format(NOT_AUTHOR, method, uri));
      print(response, Result.fail(UserError.NO_AUTH, String.format(NOT_AUTHOR, method, uri)));
    } catch (BizException e) {
      String msg = messageHelder.getMsg(e.getErrorCode().getMessageKey(), e.getArgs());
      Result<?> result = Result.fail(e.getErrorCode(), msg);
      print(response, result);
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }
  }

  private void print(HttpServletResponse response, Result<?> result) {
    try (PrintWriter writer = response.getWriter(); ) {
      writer.write(JsonUtil.toJson(result));
    } catch (IOException e) {
      log.error(e.getMessage(), e);
    }
  }
}
